#define LOG_TAG "power.can"

#include "power_can.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "elog.h"
#include "../drivers/drv_can.h"

#include "utils.h"

#include "cmd_map_rw.h"
#include "pwr_mem_tab.h"

pwr_t* get_pwr_struct(void);

/**
 * @brief 
 * @param  chn              接收通道
 * @param  msg              CAN的接收数据
 */
void on_power_received_from_isr(int chn, pwr_msg_t *msg)
{
    pwr_t *pwr = get_pwr_struct();
    if ((msg->canid & 0x0757F800) != 0x0757F800) /* 过滤功率模块的ID为0x757f8xx，这个位置可以使用CAN的ID过滤器后续优化@webbsu */
    {
        BaseType_t xHigherPriorityTaskWoken;
        if (pwr->power_q != NULL)
        {
            /* 使用非阻塞的方式，传入队列中 */
            if (!xQueueIsQueueFullFromISR(pwr->power_q))
            {
                if (!xQueueSendFromISR(pwr->power_q, msg, &xHigherPriorityTaskWoken))
                {
                    log_e("cantp power enter queue fail.");
                }
                portYIELD_FROM_ISR(xHigherPriorityTaskWoken); // 如果需要的话进行一次任务切换
            }
        }
    }
    clear_timer(&pwr->timer[0]);
    set_timer(&pwr->timer[0], PWR_RECV_TIMEOUT, 5000);
}

/**
 * @brief power初始化
 * @return int 
 */
int power_init(void)
{
    int ret = 0;
    uint16_t power_on = 0;

    pwr_t *pwr = get_pwr_struct();
    pwr->set.status = PWR_SET_IDLE_STATE;
    pwr->set.enable = pdFALSE;
    pwr->power_q = xQueueCreate(20, sizeof(pwr_msg_t));
    configASSERT(pwr->power_q);

    /* 上电处于关机状态 */
    power_on = 1;
    general_cmd_map_set(CMD_MAP_PWR, PWR_POWER_ON, (uint8_t *)&power_on, 2u);
    return ret;
}

/**
 * @brief 读取系统电压
 */
int pwr_read_sys_voltage(void)
{
    int ret = 0;

    id_t id_x = {0};
    uint8_t buffer[8] = {0};

    id_x.id.cmd         = READ_SYS_VOLTAGE_CMD;
    id_x.id.dev_id      = DEVICE_ID_SINGLE;
    id_x.id.src_addr    = CHARGE_ADDR;
    id_x.id.dest_addr   = POWER_ADDR;

    ret = stm32_fdcan2_send_message(CAN_CHN2, id_x.canid, buffer, sizeof(buffer));
    return ret;
}

/**
 * @brief 读取交流侧电压
 * @return int 
 */
int pwr_read_ac_voltage(void)
{
    int ret = 0;

    id_t id_x = {0};
    uint8_t buffer[8] = {0};

    id_x.id.cmd         = READ_AC_VOLTAGE_CMD;
    id_x.id.dev_id      = DEVICE_ID_SINGLE;
    id_x.id.src_addr    = CHARGE_ADDR;
    id_x.id.dest_addr   = CHARGE_AC_ADDR;

    ret = stm32_fdcan2_send_message(CAN_CHN2, id_x.canid, buffer, sizeof(buffer)); 
    return ret;
}

/**
 * @brief 读取功率模块的系统状态
 * @return int 
 */
int pwr_read_state(void)
{
    int ret = 0;

    id_t id_x = {0};
    uint8_t buffer[8] = {0};

    id_x.id.cmd         = READ_SYS_STATE_CMD;
    id_x.id.dev_id      = DEVICE_ID_SINGLE;
    id_x.id.src_addr    = CHARGE_ADDR;
    id_x.id.dest_addr   = CHARGE_STATE_ADDR;

    ret = stm32_fdcan2_send_message(CAN_CHN2, id_x.canid, buffer, sizeof(buffer)); 
    return ret;
}

/**
 * @brief Set the pwr on object
 * @return int 
 */
int set_pwr_on(void)
{
    int ret = 0;

    id_t id_x = {0};
    uint8_t buffer[8] = {0};
    undata16_t undata16 = {0};

    id_x.id.cmd         = SET_POWER_ON;
    id_x.id.dev_id      = DEVICE_ID_SINGLE;
    id_x.id.src_addr    = CHARGE_ADDR;
    id_x.id.dest_addr   = POWER_ADDR;

    general_cmd_map_get(CMD_MAP_PWR, PWR_POWER_ON, (uint8_t *)&undata16.data16, 2u);
    buffer[0] = undata16.data8[0];      // 开机
    // log_d("pwr state %d", buffer[0]);
    ret = stm32_fdcan2_send_message(CAN_CHN2, id_x.canid, buffer, sizeof(buffer)); 
    return ret;
}

/**
 * @brief Set the pwr out voltage curr object
 * @param  vol              输出电压
 * @param  curr             输出总电流
 * @return int              CAN总线的发送状态
 */
int set_pwr_out_voltage_curr(int vol, int curr)
{
    int ret = 0;

    id_t id_x = {0};
    uint8_t buffer[8] = {0};
    undata32_t undata32 = {0};

    id_x.id.cmd         = SET_SYS_TOTAL_VOLTAGE_CMD;
    id_x.id.dev_id      = DEVICE_ID_SINGLE;
    id_x.id.src_addr    = CHARGE_ADDR;
    id_x.id.dest_addr   = POWER_ADDR;
    
    general_cmd_map_get(CMD_MAP_PWR, PWR_OUT_VOL, (uint8_t *)&undata32.data32, 4u);
    buffer[0] = undata32.data8[3];
    buffer[1] = undata32.data8[2];
    buffer[2] = undata32.data8[1];
    buffer[3] = undata32.data8[0];
    // log_w("set power vol %d", undata32.data32);
    general_cmd_map_get(CMD_MAP_PWR, PWR_OUT_CURR, (uint8_t *)&undata32.data32, 4u);
    buffer[4] = undata32.data8[3];
    buffer[5] = undata32.data8[2];
    buffer[6] = undata32.data8[1];
    buffer[7] = undata32.data8[0];
    // log_w("set power curr %d", undata32.data32);
    ret = stm32_fdcan2_send_message(CAN_CHN2, id_x.canid, buffer, sizeof(buffer));   
    return ret;
}

/**
 * @brief                   设置电源模块设置电流/电压
 * @param  set              操作对象
 * @return int              
 */
int pwr_set_fsm(pwr_t *const set)
{
    int ret = 0;
    static uint32_t tick = 0;

    switch (set->set.status)
    {
    case PWR_SET_IDLE_STATE:
        tick = xTaskGetTickCount();
        set->set.status = PWR_SET_VOL_CURR_STATE;
        break;
    case PWR_SET_VOL_CURR_STATE:
        if (xTaskGetTickCount() - tick >= SET_TIMEOUT)
        {
            tick = xTaskGetTickCount();
            set->set.status = PWR_SET_POWER_STATE;
        }
        RUN_PERIODIC_TASK(set_pwr_out_voltage_curr(0, 0), 50u);
        break;
    case PWR_SET_POWER_STATE:
        if (xTaskGetTickCount() - tick >= SET_TIMEOUT)
        {
            set->set.enable = pdFALSE;
            set->set.status = PWR_SET_IDLE_STATE;
        }
        RUN_PERIODIC_TASK(set_pwr_on(), 50u);
        break;
    default:
        break;
    }
    return ret;
}
